package com.mo.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mo.common.Result;
import com.mo.entity.Menu;
import com.mo.entity.RoleMenu;
import com.mo.entity.UserRole;
import com.mo.enums.ResultCode;
import com.mo.service.MenuService;
import com.mo.service.RoleMenuService;
import com.mo.service.UserRoleService;
import com.mo.service.UserService;
import com.mo.utils.MenuTreeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("menu")
public class MenuController {
    @Resource
    private MenuService menuService;
    @Resource
    private UserService userService;
    @Resource
    private RoleMenuService roleMenuService;
    @Resource
    private UserRoleService userRoleService;

    @PostMapping
    @PreAuthorize("hasAuthority('sys:system:menu:add')")
    public Result addMenu(@RequestBody Menu menu) {
        boolean success = menuService.save(menu);
        if (success) {
            return Result.success();
        }
        return Result.error();
    }

    @DeleteMapping
    @PreAuthorize("hasAuthority('sys:system:menu:delete')")
    public Result deleteMenu(@RequestParam Integer menuId) {
        List<Menu> isExist = menuService.list(Wrappers.<Menu>lambdaQuery().eq(Menu::getParentId, menuId));
        if (!isExist.isEmpty()) {
            return Result.error(ResultCode.MENU_NOT_EMPTY);
        }

        boolean success = menuService.removeById(menuId);
        if (success) {
            return Result.success();
        }
        return Result.error();
    }

    @PutMapping
    @PreAuthorize("hasAuthority('sys:system:menu:update')")
    public Result updateMenu(@RequestBody Menu menu) {
        List<Menu> menuList = menuService.list(Wrappers.<Menu>lambdaQuery().eq(Menu::getParentId, menu.getMenuId()));
        boolean include = menuList.stream()
                .anyMatch(m -> menu.getParentId().equals(m.getMenuId()));
        if (include) {
            return Result.error(ResultCode.MENU_NOT_ALLOW_MOVE2_CHILDREN);
        }

        boolean success = menuService.updateById(menu);
        if (success) {
            return Result.success();
        }
        return Result.error();
    }

    @GetMapping("parent")
    public Result getParentMenuTree() {
        LambdaQueryWrapper<Menu> wrapper = Wrappers.<Menu>lambdaQuery()
                .in(Menu::getType, Arrays.asList(0, 1))
                .orderByAsc(Menu::getOrderNum);
        List<Menu> list = menuService.list(wrapper);

        // 构建一个顶层菜单用于树状显示
        Menu top = new Menu();
        top.setMenuId(0);
        top.setTitle("顶层菜单");
        top.setParentId(-1);
        // 添加到所有里面
        list.add(top);
        // 构建菜单树
//        List<Menu> menus = MenuTreeUtil.builderMenuTree(list, -1);

        List<Menu> menus = MenuTreeUtil.builderMenuTree2(list, -1);
        return Result.success(menus);
    }

    @GetMapping
    public Result getMenuTree() {
        LambdaQueryWrapper<Menu> wrapper = Wrappers.<Menu>lambdaQuery()
                .orderByAsc(Menu::getOrderNum);
        List<Menu> list = menuService.list(wrapper);

        List<Menu> menus = MenuTreeUtil.builderMenuTree2(list, 0);
        return Result.success(menus);
    }

    @GetMapping("permission")
    public Result getMenuTreeByUserId(@RequestParam Integer userId) {
        // 根据用户查角色
        LambdaQueryWrapper<UserRole> rolesWrapper = Wrappers.<UserRole>lambdaQuery()
                .eq(UserRole::getUserId, userId);
        List<Integer> roleIds = Optional.ofNullable(userRoleService.list(rolesWrapper))
                .orElse(new ArrayList<>())
                .stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());
        if (roleIds.isEmpty()) {
            return Result.success(new ArrayList<>());
        }

        // 根据角色查菜单
        LambdaQueryWrapper<RoleMenu> in = Wrappers.<RoleMenu>lambdaQuery()
                .in(RoleMenu::getRoleId, roleIds);
        List<Integer> menuIds = Optional.ofNullable(roleMenuService.list(in))
                .orElse(new ArrayList<>())
                .stream()
                .map(RoleMenu::getMenuId)
                .collect(Collectors.toList());
        if (menuIds.isEmpty()) {
            return Result.success(new ArrayList<>());
        }

        LambdaQueryWrapper<Menu> mw = Wrappers.<Menu>lambdaQuery()
                .in(Menu::getMenuId, menuIds)
                .orderByAsc(Menu::getOrderNum);
        List<Menu> menus = menuService.list(mw);
        List<Menu> finalMenu = MenuTreeUtil.builderMenuTree2(menus, 0);
        return Result.success(finalMenu);
    }

    @GetMapping("permission2")
    public Result getMenuTreeByUserId2(@RequestParam Integer userId) {
        List<Menu> menus = menuService.getUserMenuByUserId(userId);
        List<Menu> tree2 = MenuTreeUtil.builderMenuTree2(Optional.of(menus).orElse(Collections.emptyList()), 0);
        return Result.success(tree2);
    }
}
